
#include <Windows.h>
#include <d3d9.h>
#include <time.h>
#include <iostream>

using namespace std;
#pragma comment(lib,"d3d9.lib")

//Program settings
const TCHAR APPTITLE[] = TEXT("Durect3D_Windowed");
const int SCREENW = 1024;
const int SCREENH = 768;

//Direct3D object
LPDIRECT3D9 lpDirect3D = NULL;
LPDIRECT3DDEVICE9 lpDirect3DDevice = NULL;

bool gameover = false;

#define KEY_DOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1:0)

bool Game_Init(HWND hwnd) {
	lpDirect3D = Direct3DCreate9(D3D_SDK_VERSION);
	if (lpDirect3D == NULL) {
		MessageBox(hwnd, TEXT("Error initializing Direct3D"), TEXT("Error"), MB_OK);
		return FALSE;
	}
	D3DPRESENT_PARAMETERS d3dpp;
	ZeroMemory(&d3dpp, sizeof(d3dpp));
	d3dpp.Windowed = TRUE;
	d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
	d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
	d3dpp.BackBufferCount = 1;
	d3dpp.BackBufferHeight = SCREENH;
	d3dpp.BackBufferWidth = SCREENW;
	d3dpp.hDeviceWindow = hwnd;
	//create Direct3D device
	HRESULT hResult = lpDirect3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &lpDirect3DDevice);
	if (hResult != D3D_OK) {
		if (hResult == D3DERR_DEVICELOST) {
			OutputDebugString(TEXT("D3DERR_DEVICELOST\n"));
		}
		if (hResult == D3DERR_INVALIDCALL) {
			OutputDebugString(TEXT("INVALIDCALL\n"));
		}
		if (hResult == D3DERR_NOTAVAILABLE) {
			OutputDebugString(TEXT("NOTAVAILABLE\n"));
		}
		if (hResult == D3DERR_OUTOFVIDEOMEMORY) {
			OutputDebugString(TEXT("D3DERR_OUTOFVIDEOMEMORY\n"));
		}
		MessageBox(hwnd, TEXT("Error creating Direct3D device"), TEXT("Error"), MB_OK);
		return FALSE;
	}
	return TRUE;
}

void Game_Run(HWND hwnd) {
	if (!lpDirect3DDevice) {
		return;
	}
	lpDirect3DDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 255), 1.0f, 0);
	if (lpDirect3DDevice->BeginScene()) {
		lpDirect3DDevice->EndScene();
		lpDirect3DDevice->Present(NULL, NULL, NULL, NULL);
	}
	if (KEY_DOWN(VK_ESCAPE)) {
		PostMessage(hwnd, WM_DEADCHAR, 0, 0);
	}
}

void Game_End(HWND hwnd) {
	if (lpDirect3DDevice) {
		lpDirect3DDevice->Release();
		lpDirect3DDevice = NULL;
	}
	if (lpDirect3D) {
		lpDirect3D->Release();
		lpDirect3D = NULL;
	}
}

LRESULT WINAPI WinProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
	switch (msg)
	{
	case WM_DESTROY:
		gameover = true;
		break;
	default:
		break;
	}
	return DefWindowProc(hwnd, msg, wParam, lParam);
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
	WNDCLASSEX wndClass;
	MSG msg;

	wndClass.cbSize = sizeof(WNDCLASSEX);
	wndClass.lpfnWndProc = (WNDPROC)WinProc;
	wndClass.style = 0;
	wndClass.cbClsExtra = 0;
	wndClass.cbWndExtra = 0;
	wndClass.hIcon = NULL;
	wndClass.hIconSm = NULL;
	wndClass.lpszMenuName = NULL;
	wndClass.hInstance = hInstance;
	wndClass.hCursor = LoadCursor(NULL,IDC_ARROW);
	wndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
	wndClass.lpszClassName = TEXT("MainWindowClass");
	if (!RegisterClassEx(&wndClass)) {
		return FALSE;
	}

	HWND hwnd = CreateWindow(TEXT("MainWindowClass"), APPTITLE, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, SCREENW, SCREENH, (HWND)NULL, (HMENU)NULL, hInstance, (LPVOID)NULL);

	if (hwnd == 0) {
		return 0;
	}
	ShowWindow(hwnd, nCmdShow);
	UpdateWindow(hwnd);

	if (!Game_Init(hwnd)) {
		return 0;
	}
	while (!gameover) {
		if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
		Game_Run(hwnd);
	}
	Game_End(hwnd);
	return msg.wParam;
}